ヘッダーをスキップ
Oracle TimesTen In-Memory Database Java開発者およびリファレンス・ガイド
リリース6.0
B25766-01
  目次へ
目次
索引へ
索引

前へ
前へ
次へ
次へ
 

TimesTenデータの管理

この項では、TimesTenデータ・ストアのデータの処理について説明します。

内容は次のとおりです。

Javaアプリケーション内でのSQL文のコール

この項の主な内容は次のとおりです。

自動コミットの設定

TimesTen Connectionではデフォルトで自動コミットが有効になっています。Connection.setAutoCommit()を使用すると、自動コミットを有効/無効を切り替えることができます。自動コミットが無効になっている(falseに設定されている)場合は、Connection.commit()を使用して、トランザクションを手動でコミットする必要があります。

たとえば、自動コミットをオフに設定するには次のように入力します。

con.setAutoCommit(false); 
     // Report any SQLWarnings on the connection 
     // See "Reporting errors and warnings"  

SQL文の準備

複数回実行するSQL文は、Connection.prepareStatement()メソッドをコールして事前に準備しておく必要があります。

最大のパフォーマンスを得るために、パラメータ化した文を準備します。例2.3に、4つのINSERT文をパラメータ化された1つの文に置き換える方法を示します。

例2.3

値が異なる同様のINSERT文の実行:

Statement.execute("insert into t1 values (1, 2)"); 
Statement.execute("insert into t1 values (3, 4)"); 
Statement.execute("insert into t1 values (5, 6)"); 
Statement.execute("insert into t1 values (7, 8)");  
 

パラメータ化した1つのINSERT文を準備し、各文を実行する前にPreparedStatement.set...()メソッドを使用して行の値を設定する方がより効率的です。

PreparedStatement pIns =        con.PreparedStatement("insert into t1 values (?,?)"); con.commit(); pIns.setInt(1, Integer.parseInt(1)); pIns.setInt(2, Integer.parseInt(2)); pIns.executeUpdate(); pIns.setInt(1, Integer.parseInt(3)); pIns.setInt(2, Integer.parseInt(4)); pIns.executeUpdate(); pIns.setInt(1, Integer.parseInt(5)); pIns.setInt(2, Integer.parseInt(6)); pIns.executeUpdate(); pIns.setInt(1, Integer.parseInt(7)); pIns.setInt(2, Integer.parseInt(8)); pIns.executeUpdate(); con.commit(); pIns.close();
注意: SQL文を準備した後、Connection.commit()をコールして、準備によって適用されたロックを解除し、問合せ計画を保持できるようにしてください。準備された文の実行が完了した後、PreparedStatement.close()メソッドをコールして、この文に関連付けられているリソースを解放してください。

TimesTenでは、準備された文がコミットされると、自動的に共有されます。たとえば、データ・ストアへの複数の接続でそれぞれ同じ文が準備される場合、TimesTenでは、準備された最初の文が記憶されているため、2番目以降の準備が迅速に返されます。

例2.4

この例では、3つの接続に対してパラメータ化された同じINSERT文を3つ準備します。接続con1に対して最初に準備するINSERTは、con2接続およびcon3接続で共有されるため、pIns2およびpIns3の準備操作が高速に行われます。

Connection con1; 
Connection con2; 
Connection con3; 
..... 
PreparedStatement pIns1 = con1.prepareStatement 
                 ("insert into t1 values (?,?)"); 
con1.commit(); 
PreparedStatement pIns2 = con2.prepareStatement 
                 ("insert into t1 values (?,?)"); 
con2.commit(); 
PreparedStatement pIns3 = con3.prepareStatement 
                 ("insert into t1 values (?,?)"); 
con3.commit(); 
注意: 結合順序、索引、ロックなど、すべてのチューニング・オプションが共有される文に適している必要があります。また、準備された文が一時表を参照する場合、この文は1つの接続内でのみ共有されます。
注意: TimesTenでは、JDBC 3.0仕様で指定されているように、PooledConnection用に準備された文のプールもサポートされています。最大サイズのプールを構成するには、ObservableConnectionDS.setMaxStatements()を設定します。設定した後、この値は変更しないでください。

事前にSQL文を準備することによるパフォーマンス上の利点については、「文の事前準備」を参照してください。

SQL文の実行

SQLを使用してTimesTenデータ・ストアのデータを管理する方法については、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』のTimesTenデータ・ストアのデータの処理に関する章を参照してください。この項では、Connection.createStatement()メソッド、Statement.executeUpdate()メソッドおよびStatement.executeQuery()メソッドを使用して、Javaアプリケーション内でSQL文を実行する方法について説明します。

SQL文の準備」で説明したとおり事前に文が準備されていない場合は、SQL文の特性および返された結果セットに応じて、Statement.execute()Statement.executeUpdate()Statement.executeQuery()などのStatement実行メソッドを使用します。

事前に準備されたSQL文には、PreparedStatement.execute()PreparedStatement.executeUpdate()PreparedStatement.executeQuery()などのPreparedStatement実行メソッドを使用します。

execute()メソッドは、結果セットがある場合はTrueを返し(SELECTなど)、結果セットがない場合はFalseを返します(INSERT、UPDATE、DELETEなど)。executeUpdate()メソッドは、影響を受ける行数を返します。たとえば、INSERT文を実行すると、executeUpdate()メソッドは挿入された行数を返します。executeQuery()メソッドは結果セットを返すため、結果セットが必要な場合(SELECTの実行時など)にのみコールする必要があります。

注意: TimesTenで生成された結果セットの使用に関する注意事項は、「結果セットの使用」を参照してください。
例2.5

Statement.executeUpdate()メソッドを使用して、xyz.customer表へのINSERTを実行するには、次のように入力します。

Connection con; 
Statement stmt; 
. . . . . .  
try { 
    stmt = con.createStatement(); 
    int numRows = stmt.executeUpdate("insert into xyz.customer 
       values" + "(40, 'West', 'Big Dish', '123 Signal St.');"); 
}
catch (SQLException ex) { 
    ..... 
} 
例2.6

この例では、Statement.executeQuery()メソッドを使用して、xyz.customer表に対してSELECTを実行し、返されたResultSetを表示します。

Statement stmt; 
. . . . . .  
try { 
  ResultSet rs = stmt.executeQuery("select cust_num, region, " + 
                       "name, address from xyz.customer;"); 
  System.out.println("Fetching result set..."); 
  while (rs.next()) { 
     System.out.println("\n  Customer number: " + rs.getInt(1)); 
     System.out.println("  Region: " + rs.getString(2)); 
     System.out.println("  Name: " + rs.getString(3)); 
     System.out.println("  Address: " + rs.getString(4)); 
     } 
  }
catch (SQLException ex) { 
    ex.printStackTrace(); 
} 
例2.7

この例では、PreparedStatement.executeQuery()メソッドを使用して、準備済のSELECT文を実行し、返されたResultSetを表示します。

PreparedStatement pSel = con.prepareStatement("select cust_num, " + 
                         "region, name, address " + 
                         "from xyz.customer;"); 
con.commit(); 
try { 
  ResultSet rs = pSel.executeQuery(); 
  while (rs.next()) { 
      System.out.println("\n  Customer number: " + rs.getInt(1)); 
      System.out.println("  Region: " + rs.getString(2)); 
      System.out.println("  Name: " + rs.getString(3)); 
      System.out.println("  Address: " + rs.getString(4)); 
    } 
}
catch (SQLException ex) { 
    ex.printStackTrace(); 
} 

SQL文の実行に対するタイムアウト値の設定

TimesTenでは、DSN属性SqlQueryTimeoutを設定して、すべての接続に対して問合せのタイムアウト期間を指定できます。DSN仕様にSqlQueryTimeoutを設定すると、その値が、今後のデータ・ストアへのすべての接続のデフォルト値となります。

現行の接続のSqlQueryTimeout値を上書きするには、Statement.setQueryTimeout()メソッドをコールして、データ・ストアでSQL問合せが実行される制限時間(秒)を指定します。TimesTenでは、タイムアウト・トリガーが起動されると、実行中の問合せに対してタイムアウトが指示されます。タイムアウト・メッセージが問合せに達するまでにタイムラグが発生する可能性あるため、問合せが終了するまでの実際の時間は、タイムアウト・メッセージが問合せに達するまでにかかる時間と指定したタイムアウト値を加算した時間になります。

Statement.setQueryTimeout()メソッドは、SQL文がアクティブに実行されている場合にのみ動作します。処理のコミット中またはロールバック中にタイムアウトは発生しません。多数のUPDATE、DELETEまたはINSERTを実行するトランザクションでは、コミットまたはロールバックが完了するまでに時間がかかる場合があります。その間、タイムアウト値は無視されます。

注意: TimesTenのLockWaitとSqlQueryTimeoutは別々の機能であり、別の値を指定できます。TimesTenは、ロック・タイムアウト値およびSQLQueryTimeout値の両方を確認します。TimesTenは、すべてのスレッドを確認し、ロック・タイムアウトまたはSQL問合せタイムアウトのいずれかが指定されているスリープ中のプロセスのスリープ状態を解除して、実行中のスレッドに適切なSqlQueryTimeout値を指定します。LockWaitタイムアウト値およびSqlQueryTimeout値の両方が指定されている場合は、まず、2つの値の小さい方の値によってタイムアウトが発生します。

すべての処理の組合せ: SQLの準備と実行

この例では、INSERT文とSELECT文を準備し、INSERTを2回実行します。また、SELECTを実行し、返された結果セットを印刷します。作業例については、level1.javaデモを参照してください。

Connection con; 
Statement stmt; 
// Disable auto-commit 
con.setAutoCommit(false); 
     // Report any SQLWarnings on the connection 
     // See "Reporting errors and warnings"  
// Prepare a parameterized INSERT and a SELECT Statement 
PreparedStatement pIns = con.prepareStatement("insert into
xyz.customer values (?,?,?,?)"); 
PreparedStatement pSel = con.prepareStatement 
   ("select cust_num, region, name, " + 
    "address from xyz.customer"); 
// Prepare is a transaction; must commit to release locks 
con.commit(); 
// Data for first INSERT statement 
pIns.setInt(1, Integer.parseInt(100));  
pIns.setString(2, 'N');  
pIns.setString(3, 'Fiberifics');  
pIns.setString(4,'123 any street');  
// Execute the INSERT statement 
pIns.executeUpdate(); 
// Data for second INSERT statement 
pIns.setInt(1, Integer.parseInt(101));  
pIns.setString(2, 'N');  
pIns.setString(3,'Natural Foods Co.');  
pIns.setString(4,'5150 Johnson Rd');  
// Execute the INSERT statement 
pIns.executeUpdate(); 
// Commit the inserts 
con.commit(); 
// Done with INSERTs, so close the prepared statement 
pIns.close(); 
// Report any SQLWarnings on the connection 
reportSQLWarnings(con.getWarnings()); 
CheckIfStopIsRequested(); 
// Execute the prepared SELECT statement 
ResultSet rs = pSel.executeQuery(); 
System.out.println("Fetching result set..."); 
while (rs.next()) { 
    System.out.println("\n Customer number: " + rs.getInt(1)); 
    System.out.println("  Region: " + rs.getString(2)); 
    System.out.println("  Name: " + rs.getString(3)); 
    System.out.println("  Address: " + rs.getString(4)); 
} 
// Close the result set. 
rs.close(); 
// Commit the select - yes selects need to be committed too 
con.commit(); 
// Close the select statement - we're done with it 
pSel.close(); 

複数のデータ行のフェッチ

TimesTenデータ・ストアから複数のデータ行をフェッチすると、コミット読取り分離レベルが設定されたデータ・ストアに接続しているアプリケーションのパフォーマンスを向上させることができます。

プリフェッチされる行数を指定するには、次の手順を実行します。

注意: 直接リンクされたアプリケーションでのみ、TimesTenのプリフェッチ・カウント拡張を使用できます。

プリフェッチ数を0(ゼロ)に設定すると、TimesTenは、データ・ストアに設定した分離レベルに応じて、デフォルトの値を使用します。シリアライズ可能分離モードでは、デフォルトのプリフェッチの値は128です。コミット読取り分離モードでは、デフォルトは5です。デフォルトのプリフェッチの値はほとんどのアプリケーションに最適な設定です。

プリフェッチの値は、0(ゼロ)から128までの任意の整数に再設定できます。シリアライズ可能分離モードが使用されている場合にプリフェッチ数を再設定すると、コミットされるまでロックが設定されます。このため、フェッチと実行の間で遅延が発生した場合は、ロック期間が長くなります。コミット読取り分離モードでは、フェッチが行われるまで読み取られた行のコピーが保持されるため、領域を使用する複数のコピーが存在する場合があります。

プリフェッチを無効にするには、プリフェッチ数を1に設定します。

TimesTenConnection.getTtPrefetchCount()をコールして、現行のプリフェッチ値を確認します。

例2.8

この例では、ttIsql prefetchcountコマンドを使用して、接続のプリフェッチ数を6に設定します。

> ttIsql RunData_tt51 
Command > prefetchcount 6; 
例2.9

この例では、setTtPrefetchCount()を使用して、プリフェッチ数を10に設定し、getTtPrefetchCount()を使用して、カウント変数のプリフェッチ数を返します。

TimesTenConnection con =  
     (TimesTenConnection) DriverManager.getConnection(url); 
// set prefech count to 10 for this connection 
con.setTtPrefetchCount(10); 
// Return the prefetch count to the 'count' variable. 
int count = con.getTtPrefetchCount();  

バッチでの複数のSQL文の実行

StatementオブジェクトおよびPreparedStatementオブジェクトに対してaddBatch()メソッドおよびexecuteBatch()メソッドをコールすると、パフォーマンスを向上させることができます。

Statementオブジェクトの場合、バッチは、通常、一連のINSERT文またはUPDATE文で構成されています。結果セットを返す文は、バッチでは使用できません。addBatch()メソッドをコールすると、バッチにSQL文が追加されます。バッチに関連付けられている一連のSQL文は、executeBatch()メソッドによって実行されます。次に例を示します。

// turn off autocommit 
conn.setAutoCommit(false); 
Statement stmt = conn.createStatement(); 
stmt.addBatch("INSERT INTO employees VALUES (1000, 'Joe
Jones')"); 
stmt.addBatch("INSERT INTO departments VALUES (260, 'Shoe')"); 
stmt.addBatch("INSERT INTO emp_dept VALUES (1000, 260)"); 
// submit a batch of update commands for execution 
int[] updateCounts = stmt.executeBatch(); 
conn.commit (); 
 

PreparedStatementオブジェクトの場合、バッチは準備された一連の文の入力パラメータで構成されています。準備された文のパラメータは、setコールを実行した後、addBatch()コールを実行することでバッチに追加されます。バッチはexecuteBatch()メソッドを介して実行されます。次に例を示します。

// turn off autocommit conn.setAutoCommit(false); PreparedStatement stmt = conn.prepareStatement( "INSERT INTO employees VALUES (?, ?)"); // first set of parameters stmt.setInt(1, 2000); stmt.setString(2, "Kelly Kaufmann"); stmt.addBatch(); // second set of parameters stmt.setInt(1, 3000); stmt.setString(2, "Bill Barnes"); stmt.addBatch(); // submit the batch for execution. Check update counts int[] updateCounts = stmt.executeBatch(); conn.commit ();

結果セットの使用

問合せ以外に、一部のメソッドおよび組込みプロシージャでもTimesTenデータがResultSetオブジェクトの形式で返されます。この項では、TimesTenからのResultSetオブジェクトの使用について説明します。